Release 10.1A: OpenEdge Data Management:
DataServer for Microsoft SQL Server
Block cursors
Block cursors are available as a performance enhancement. They allow blocks of records to be bound and fetched together from a single database request, thus reducing the network overhead and minimizing record copies for 4GL queries and finds, and minimizing record copies.
Considering block cursors and firehose cursors
Block cursors are the default behavior replacing look-ahead cursors for
NO-LOCKqueries that are processed on the server side. ANO-LOCKquery is one that executes with theNO-LOCKlock condition attached to its 4GL statement.Block cursors are the preferred choice to process
NO-LOCKqueries on the server side. However, server-side cursor processing is not the primary choice overall. Firehose cursors, providing optimum performance forNO-LOCKqueries, surpasses the benefits of block cursors because they are client-based. For an in depth presentation of firehose cursors, see the "Firehose and Fast Forward-Only Cursors" section.Additional details about block cursor behavior
DataServer connections that run at the read uncommitted isolation level will also execute queries that specify the
SHARE-LOCKcondition asNO-LOCKqueries and will also utilize block cursors for their result sets. You can shut off block cursor behavior and revert back to look-ahead cursors forNO-LOCKqueries by setting the-DsrvPRGRS_BLOCK_CURS,0. If you leave block cursors on but wish to turn off the block and/or look-ahead cursor optimizations for a specific query, you can set theQUERY-TUNINGoptionQUERY-TUNING(NO-LOOKAHEAD)on your 4GL statement.While block cursors increase efficiency, they might also require more memory than look-ahead cursors. Block cursors will try to reuse memory from previous result sets whenever possible. You can adjust the memory available to block cursors according to your specifications. Adjust the cache size of an individual block with the same connection-level parameter you used to set the look-ahead cache size. The
-DsrvQT_CACHE_SIZEoption allows you to specify at connect time how large the block cache should be for individual query results. When block cursors are active, the defaultQT_CACHE_SIZEis set to 10,000 bytes. When look-ahead cursors are active, this size defaults to 30,000 bytes.You can override the connection-level
QT_CACHE_SIZEat the statement level by setting theQUERY-TUNINGoption calledCACHE-SIZEon the query itself. Determining the proper block size should be based on the maximum length of your returned records multiplied by the expected number of resultant rows and then compared to your available memory. Whenever an existing block is not reused, the block of memory allocated for the query will be adjusted downward to an exact multiple of the number of rows that can fit into the allocated area.To prevent large applications from potentially overutilizing memory for block cursors, two other settings can be adjusted to limit the amount of memory available to block cursors. The first is the maximum block memory usage per table. If you have multiple queries open against the same table simultaneously, each query uses its own query block. The
-DsrvPRGRS_TABLE_BLOCKSIZEoption puts an upper limit on the total memory available to query blocks of an individual table. This number should normally be set larger than theQT_CACHE_SIZEvalue. It can be set as high as two or three times theQT_CACHE_SIZE. If the maximum block memory available to the table will be exceeded by allocating space for the currentNO-LOCKquery in your 4GL, the query is instead executed with a look-ahead cursor. The default maximum block memory area per table is set at 65,000 bytes.The second adjustment switch available is the
-DsrvPRGRS_MAX_BLOCKSIZEoption. This value sets an upper limit to the overall memory provided to block cursors, irrespective of per table allocations. The default maximum is 1048576 bytes (or 1MB). Your accumulated total memory allocated for block cursors will not exceed this value. If allocating block cursor memory for aNO-LOCKquery in your 4GL will cause this limit to be exceeded, the query would instead be executed with a look-ahead cursor. ThePRGRS_MAX_BLOCKSIZEvalue should be set with respect to the amount of memory available on your machine. If you are running in client-server mode, the number should be set with respect to both the available memory on the server machine as well as the number of clients that will be connecting.The following example uses the state table in the demo database, which has a maximum record size of 84 bytes:
In this example, the
QUERY-TUNINGCACHE-SIZEvalue overrides the-DsrvQT_CACHE_SIZEquery block size default of 10,000 bytes. Ten records at 84 bytes per record totals 840 bytes in the query block. If a previously established block is located for that table that is greater than or equal to the requested size, it will be reused. However, if a new block is established instead, its memory allocation will be adjusted downward to 840 bytes in order to fit an exact multiple of rows in the block. Then, if the result set contains 30 records, the query block will get refilled three times before the end of the result set if read sequentially.Block cursors on vs. off
Block cursors are the default over lookahead cursors when
PRGRS_BLOCK_CURSis enabled and a server-side cursor is needed. The switch-DsrvPRGRS_BLOCK_CURS,0will turn off block cursors in SQL Server if you want to turn off the feature for this connection. You can always disable block cursors for a specific query by disabling lookahead with a query tuning option:QUERY-TUNING(NO-LOOKAHEAD). Block cursors is not a one size fits all feature. There are application environments where the default values for block allocation sizes can result in either under-utilization or over-utilization of memory. See the "Using the block cursor switches" section for information on tuning the amount of memory that block cursors utilizes.For any given query, the use of a block cursor or a lookahead cursor is mutually exclusive. In certain circumstances, block cursors will downgrade to lookahead. These are the criteria:
- When
-DsrvBINDING,0is set. When binding is off, block cursors are disabled.- Predictable single record result sets —
FORFIRST/FORLASTor dynamic find operations.- The
PRGRS_TABLE_BLOCKSIZEhas been exceeded and all existing block table space is in-use by open cursors.- The accumulation of memory allocated to all block cursors has reached
PRGRS_MAX_BLOCKSIZE.Note: The macro- The
QT_CACHE_SIZEquery-tuning (CACHE-SIZE) value is not larger than 2 times the maximum row size. At least 2 rows need to fit in the result block to use a block cursor.BLOCKBUF_AVAILABLEcan be used to determine if the current query is or is not using a block cursor.Block vs. lookahead cursors
Block cursors and lookahead cursors are both associated with
NO-LOCKqueries. These are queries where the lock status has been explicitly set toNO-LOCKor where the lock status has been explicitly set toSHARE-LOCKand the transaction isolation level is set to read-uncommitted. Block cursors and lookahead cursors are mutually exclusive.Block cursors are more efficient than lookahead cursors for the following reasons:
- The results of a query are bound directly to the area from which they are copied into the record buffer on the client. Lookahead cursors copy out of a common bind area into the lookahead cache and then are copied into client record buffer resulting in multiple copies of the data.
- The fetch process used by block cursors fetches multiple rows at a time, reducing the number of driver calls and potentially reducing the total number of network round trips to the server.
- Block cursor memory is preallocated prior to fetching a result set, whereas lookahead cursors post allocate memory as records are fetched from the result set.
- Block cursors are directly linked to the result set binding feature whereas lookahead cursors have no particular dependency on whether binding or late-binding is active.
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |